package com.decent.common.validator;

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Objects;

/**
 * 时间范围约束验证器
 *
 * @author: wangyan
 * @date: 2021/12/16
 */
public class CheckTimeRangeValidator implements ConstraintValidator<CheckTimeRange, Object> {

    private String startTimeName;
    private String endTimeName;
    private int limitDays;

    @Override
    public void initialize(CheckTimeRange checkTimeRange) {
        startTimeName = checkTimeRange.startTime();
        endTimeName = checkTimeRange.endTime();
        limitDays = checkTimeRange.limitDays();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        // 禁用默认的message的值
        context.disableDefaultConstraintViolation();
        BeanWrapper beanWrapper = new BeanWrapperImpl(value);
        Object startTime = beanWrapper.getPropertyValue(startTimeName);
        Object endTime = beanWrapper.getPropertyValue(endTimeName);
        if (Objects.isNull(startTime) || Objects.isNull(endTime)) {
            // 重新添加错误提示语句
            context.buildConstraintViolationWithTemplate("请选择开始时间及结束时间")
                    .addConstraintViolation();
            return false;
        }
        if (startTime instanceof LocalDateTime && endTime instanceof LocalDateTime) {
            LocalDateTime newStartTime = (LocalDateTime) startTime;
            LocalDateTime newEndTime = (LocalDateTime) endTime;
            if (newStartTime.isAfter(newEndTime)) {
                // 重新添加错误提示语句
                context.buildConstraintViolationWithTemplate("开始时间不能在结束时间之后")
                        .addConstraintViolation();
                return false;
            }
            Duration duration = Duration.between(newStartTime, newEndTime);
            if (duration.toDays() > limitDays) {
                // 重新添加错误提示语句
                context.buildConstraintViolationWithTemplate(String.format("时间间隔不能超过%s天", limitDays))
                        .addConstraintViolation();
                return false;
            }
            return true;
        }
        if (startTime instanceof LocalDate && endTime instanceof LocalDate) {
            LocalDate newStartTime = (LocalDate) startTime;
            LocalDate newEndTime = (LocalDate) endTime;
            if (newStartTime.isAfter(newEndTime)) {
                // 重新添加错误提示语句
                context.buildConstraintViolationWithTemplate("开始时间不能在结束时间之后")
                        .addConstraintViolation();
                return false;
            }
            long intervalDays = newEndTime.toEpochDay() - newStartTime.toEpochDay();
            if (intervalDays > limitDays) {
                // 重新添加错误提示语句
                context.buildConstraintViolationWithTemplate(String.format("时间间隔不能超过%s天", limitDays))
                        .addConstraintViolation();
                return false;
            }
            return true;
        }
        // 重新添加错误提示语句
        context.buildConstraintViolationWithTemplate("时间类型有误").addConstraintViolation();
        return false;
    }

}
